package com.hdjd.service.imp;

import com.hdjd.dao.*;
import com.hdjd.entities.*;
import com.hdjd.service.GoodsService;
import com.hdjd.util.FileOpinionImgUpload;
import com.hdjd.util.FileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 刘子强
 * 2021/1/25 17:23
 */
@Service
public class GoodsServiceImp implements GoodsService {
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private OrderDetailDao orderDetailDao;
    @Autowired
    private GoodsStockDao goodsStockDao;
    @Autowired
    private GoodsInDao goodsInDao;
    @Autowired
    private GoodsReturnDao goodsReturnDao;
    @Autowired
    private GoodsImgDao goodsImgDao;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private OpinionDao opinionDao;
    @Autowired
    private FundRecordDao fundRecordDao;
    @Autowired
    private ReceiveAddressDao receiveAddressDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ShopCarDao shopCarDao;
    @Autowired
    private OpinionFileDao opinionFileDao;

    //根据商家id查询该商家所有商品（也可以根据商品名称模糊查询，根据商品状态查询）
    @Override
    public List<Goods> selectGoodsListByAccId(Integer accId, Integer goStatus, String goNm, Integer pageCurrent, Integer pageSize){
        List<Goods> goodsList = this.goodsDao.selectGoodsListByAccId(accId, goStatus, goNm, (pageCurrent-1)*pageSize, pageSize);

        //获得系统当前日期
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = df.format(date);

        Calendar c = new GregorianCalendar();
        //将当前日期变为日历，并减 1 天，再转换回来变成日期，获取当前系统日期前一天的日期
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, -1);
        date = c.getTime();
        String stkDate = df.format(date);

        for (Goods goods : goodsList) {
            Integer goodsStockNum = this.getCurrentGoodsStockNumByGoId(goods.getGoId());
            goods.setGoodsStock(goodsStockNum);
        }
        return goodsList;
    }

    @Override
    public boolean insertGoods(Goods goods) {
        boolean flag = this.goodsDao.insertGoods(goods);
        return flag;
    }

    @Override
    public List<SellNum> selectGoodsListByGoNmOrSelectAll(Integer accId,String goNm,Integer pageCurrent, Integer pageSize) {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
        Calendar calendar = Calendar.getInstance();
        String startDate = sdf.format(calendar.getTime());//查询当前年和月份

        Integer schoolId = this.accountDao.selectSchoolIdByAccId(accId);
        List<SellNum> sellNums = this.orderDetailDao.selectAllGoodsSellNumByStartDateAndSchoolId(goNm,startDate,schoolId,(pageCurrent-1)*pageSize,pageSize) ;

//        List<Goods> goodsList = new ArrayList<>();
//        List<Map<String,Object>> sellNum = this.orderDetailDao.selectAllGoodsSellNumByStartDateAndSchoolId(goNm,startDate,schoolId,(pageCurrent-1)*pageSize,pageSize);
//        for (Map<String, Object> map : sellNum) { //遍历查询到的月销售量和商品Id
//            Integer goId = (Integer)map.get("goId");
//            BigDecimal bigDecimal = (BigDecimal)map.get("saleNum");
//            Integer saleNum = Integer.parseInt(bigDecimal.toString());
//            Goods goods = this.goodsDao.selectGoodsByGoId(goId); //根据商品Id查询商品信息
//            goods.setSellNum(saleNum);//设置月销售量
//            goodsList.add(goods);
//        }
        return sellNums;
    }

    @Override
    public boolean updateGoodsByGoId(Goods goods) {
        boolean flag = this.goodsDao.updateGoodsByGoId(goods);
        return flag;
    }

    @Override
    public Goods selectGoodsByGoId(Integer goId) {
        Goods goods = this.goodsDao.selectGoodsByGoId(goId);
        goods.setGoodsStock(this.getCurrentGoodsStockNumByGoId(goId));
        goods.setReputablyRatio(this.getReputablyRatio(goId));
        return goods;
    }

    @Override
    public boolean OnShelfAndOffShelfGoodsByGoId(Integer goId, Integer goStatus) {
        boolean flag = this.goodsDao.OnShelfAndOffShelfGoodsByGoId(goId, goStatus);
        return flag;
    }

    //商品进货
    @Override
    @Transactional
    public boolean insertGoodsIn(GoodsIn goodsIn, Integer accId) {
        //计算进货总价
        Double inAllpri = goodsIn.getInNum() * goodsIn.getInPri();
        goodsIn.setInAllpri(inAllpri);
        //获取系统当前时间
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = df.format(date);
        //设置进货时间
        goodsIn.setInTime(currentTime);

        //根据商品id获取进货的商品名称
        Goods goods = this.goodsDao.selectGoodsByGoId(goodsIn.getGoId());
        String goNm = goods.getGoNm();
        goodsIn.setGoNm(goNm);
        //1.新增进货记录
        this.goodsInDao.insertGoodsIn(goodsIn);

        //2.查询商家余额
        Double accBalance = this.accountDao.selectAccBalanceByAccId(accId);
        if(accBalance < inAllpri){      //当商家余额不足时，抛出异常
            throw new RuntimeException("进货失败，商家余额！");
        }

        //3.减少商家账户余额
        this.accountDao.updateAccBalanceByAccId(accId, -inAllpri);

        //4.再次查询商家余额
        accBalance = this.accountDao.selectAccBalanceByAccId(accId);

        FundRecord fundRecord = new FundRecord();
        fundRecord.setAccId(accId);
        fundRecord.setDealAmount(inAllpri);
        fundRecord.setRecordBalance(accBalance);
        fundRecord.setRecordType(3); //资金记录类型设置为 3 (购物)
        fundRecord.setAddTime(currentTime);

        //5.向资金记录表添加退款记录
        boolean flag = this.fundRecordDao.insertFundRecord(fundRecord);
        return flag;
    }

    //商品退货
    @Override
    @Transactional
    public boolean insertGoodsReturn(Integer inId, Integer retNum, Integer accId) {
        //根据进货id查询进货信息
        GoodsIn goodsIn = this.goodsInDao.selectGoodsInByInId(inId);

        GoodsReturn goodsReturn = new GoodsReturn();
        //退货数量
        goodsReturn.setRetNum(retNum);
        //进货数量
        Integer inNum = goodsIn.getInNum();
        if(retNum > inNum || retNum < 0){
            throw new RuntimeException("退货数量大于进货数量");
        }
        //退货商品单价
        Double retPri = goodsIn.getInPri();
        goodsReturn.setRetPri(retPri);
        //退货总额
        Double retTotalPri = retPri * retNum;
        goodsReturn.setRetTotalPri(retTotalPri);
        //商品id
        goodsReturn.setGoId(goodsIn.getGoId());
        //商品名称
        String goNm = goodsIn.getGoNm();
        goodsReturn.setGoNm(goNm);
        //供应商
        String supplier = goodsIn.getSupplier();
        goodsReturn.setSupplier(supplier);
        //退货时间
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = df.format(date);
        goodsReturn.setRetTime(currentTime);
        //1.新增退货记录
        this.goodsReturnDao.insertGoodsReturn(goodsReturn);
        //2.增加商家账户余额
        this.accountDao.updateAccBalanceByAccId(accId, retTotalPri);
        //3.查询商家余额
        Double accBalance = this.accountDao.selectAccBalanceByAccId(accId);
        FundRecord fundRecord = new FundRecord();
        fundRecord.setAccId(accId);
        fundRecord.setDealAmount(retTotalPri);
        fundRecord.setRecordBalance(accBalance);
        fundRecord.setRecordType(6); //资金记录类型设置为 6 (退款)
        fundRecord.setAddTime(currentTime);

        //4.修改进货状态为 2
        goodsIn.setInStatus("2");
        this.goodsInDao.updateGoodsInByInId(goodsIn);

        //5.向资金记录表添加退款记录
        boolean flag = this.fundRecordDao.insertFundRecord(fundRecord);
        return flag;
    }

    //插入商品图片
    @Override
    @Transactional
    public boolean insertGoodsImg(Integer goId, String imgIds, String imgDefault, MultipartFile img, HttpServletRequest request) {
        GoodsImg goodsImg = new GoodsImg();
        goodsImg.setGoId(goId);

        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = df.format(date);

        //判断字符串不为null或不为空串，用 equals，有值的放前面
        if(imgIds != null && !("").equals(imgIds)){
            //用逗号分隔 商品图片id ，再根据图片id插入图片停用时间
            String[] imgIdArray = imgIds.split(",");
            for (String s : imgIdArray) {
                //停用之前的图片，插入停用时间 (因为更换新图片，所以之前的图片的停用时间就是当前系统时间)
                Integer imgId = Integer.parseInt(s);
                this.goodsImgDao.updateGoodsImgStoptmByImgId(imgId, currentTime);
            }
        }

        String imgUrl = null;
        try {
            //调用util包中文件上传类(FileUpload)中方法，将上传的图片保存到本地，并返回图片新名称
            imgUrl = FileUpload.fileUpload(img, request);
        } catch (Exception e) {
            throw new RuntimeException("图片保存失败");
        }


        goodsImg.setImgStarttm(currentTime);
        goodsImg.setImgUrl(imgUrl);
        goodsImg.setImgDefault(imgDefault);
        //将图片信息存储到数据库
        boolean flag = this.goodsImgDao.insertGoodsImg(goodsImg);
        return flag;
    }

    @Override
    public boolean insertOpinionImg(Integer opiId, MultipartFile img, HttpServletRequest request) {
        OpinionFile opinionFile = new OpinionFile();
        String imgUrl = null;
        try {
            //调用util包中文件上传类(FileUpload)中方法，将上传的图片保存到本地，并返回图片新名称
            imgUrl = FileOpinionImgUpload.fileUpload(img, request);
        } catch (Exception e) {
            throw new RuntimeException("图片保存失败");
        }
        opinionFile.setFileUrl(imgUrl);
        opinionFile.setOpiId(opiId);
        int flag = this.opinionFileDao.insertSelective(opinionFile);
        if (flag != 0){
            return true;
        }
        return false;
    }

    @Override
    public List<String> selectGoodsImgUrl(Integer goId) {
        String defaultImg = this.goodsImgDao.selectImgUrlByGoIdAndDefaultProperty(goId);//查询默认商品图片
        List<String> imgUrl = new ArrayList<>();
        imgUrl.add(defaultImg);
        imgUrl.addAll(this.goodsImgDao.selectAllUnDefaultImgUrlByGoId(goId));//查询所有非默认商品图片
        return imgUrl;
    }

    //根据商品id获取商品最新库存
    @Override
    public Integer getCurrentGoodsStockNumByGoId(Integer goId) {
        //获得系统当前日期
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = df.format(date);
        Calendar c = new GregorianCalendar();
        //将当前日期变为日历，并减 1 天，再转换回来变成日期，获取当前系统日期前一天的日期
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, -1);
        date = c.getTime();
        String stkDate = df.format(date);

        //获得系统当前日期发货总数量
        Integer deliverGoodsNum = this.orderDetailDao.selectDeliverGoodsNum(goId, currentDate);
        if(deliverGoodsNum == null){
            deliverGoodsNum = 0;
        }
        //获得系统当前日期订单退货的总数量
        Integer orderReturnGoodsNum = this.orderDetailDao.selectOrderReturnGoodsNum(goId, currentDate);
        if(orderReturnGoodsNum == null){
            orderReturnGoodsNum =0;
        }
        //获取前一天的库存数量
        GoodsStock goodsStock = this.goodsStockDao.selectGoodsStockByGoIdAndStkDate(goId, stkDate);
        Integer stkNum = 0;
        if(goodsStock != null){
            stkNum = goodsStock.getStkNum();
        }
        //查询系统当前日期的进货数量
       Integer inNum = this.goodsInDao.sumGoodsInNumByGoIdAndInTime(goId, currentDate);
        if(inNum == null){
            inNum = 0;
        }
        //获取系统当前日期的退货数量
        Integer retNum = this.goodsReturnDao.sumGoodsRetNumByGoIdAndRetTime(goId, currentDate);
        if(retNum == null){
            retNum = 0;
        }
        //商品时时库存
        Integer goodsStockNum = stkNum + inNum - retNum - deliverGoodsNum + orderReturnGoodsNum;

        return goodsStockNum;
    }

    @Override
    public Integer getReputablyRatio(Integer goId) {
        Integer allOpinionNum = this.opinionDao.selectGoodsOpinionNum(goId);//所有评价数
        Integer reputablyNum = this.opinionDao.selectGoodsReputablyNum(goId);//好评数
        if (allOpinionNum != null && allOpinionNum != 0){
            if (reputablyNum == null){
                return 0;
            }
            double opinionNum = (double) allOpinionNum;
            Integer reputablyRatio = (int)((reputablyNum/opinionNum)*100);
            return reputablyRatio;
        }else {
            return 0;
        }
    }

    @Override
    public List<Opinion> selectOpinionInfoByGoId(Integer goId,Integer opiType,Integer pageCurrent,Integer pageSize) {
        List<Opinion> opinions = null;
        try {
            opinions = this.opinionDao.selectOpinionByGoIdOrOpiTypeAndGoId(goId,opiType,(pageCurrent-1)*pageSize,pageSize);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        if (opinions != null){
            for (Opinion opinion : opinions) {
                opinion.setAccName(this.accountDao.selectAccountByAccId(opinion.getAccId()).getAccName());
                opinion.setAccImg(this.accountDao.selectAccountByAccId(opinion.getAccId()).getAccImg());
            }
           return opinions;
        }
        return null;
    }

    @Override
    public int selectOpinionNumByGoId(Integer goId, Integer opiType) {
        return this.opinionDao.selectOpinionNumByGoIdOrOpiTypeAndGoId(goId, opiType);
    }

    @Transactional
    @Override
    public Integer buyGoodsByAccIdAndGoId(Integer accId, String[] goIds) {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        String currentTime = sdf.format(calendar.getTime());
        Order order = new Order();
        //新增只有账户Id的空订单
        order.setAccId(accId);
        this.orderDao.insertSelective(order);
        //查询用户的数据
        Account account = this.accountDao.selectAccountByAccId(accId);
        for (String goIdString : goIds) {
            Integer goId = Integer.parseInt(goIdString);

            Goods goods = this.goodsDao.selectGoodsByGoId(goId);
            ShopCar shopCar = this.shopCarDao.selectShopCartByAccIdAndGoId(goId,accId);
            OrderDetail orderDetail = new OrderDetail();
            //新增订单详细
            orderDetail.setAccId(accId);
            orderDetail.setAccName(account.getAccName());
            orderDetail.setOrdId(order.getOrdId());
            orderDetail.setGoId(goId);
            orderDetail.setGoNm(goods.getGoNm());
            orderDetail.setGoPri(goods.getGoPri());
            orderDetail.setOrdStatus("1");
            orderDetail.setPlaceTime(currentTime);
            if (goIds.length > 1 || shopCar != null){
                //根据购物车增加订单详细
                orderDetail.setGoNum(shopCar.getGoNum());
                orderDetail.setTotalPrice(shopCar.getTotalPri());
                orderDetail.setShipTotalPrice(goods.getGoDismoney()*shopCar.getGoNum());
                this.shopCarDao.deleteByPrimaryKey(shopCar.getShopCarId());
            }
            if (goIds.length == 1 && shopCar == null){
                //新增订单详细
                orderDetail.setGoNum(1);
                orderDetail.setTotalPrice(goods.getGoPri());
                orderDetail.setShipTotalPrice(goods.getGoDismoney());
            }

            this.orderDetailDao.insertSelective(orderDetail);
        }

        //更新订单
        order.setOrdId(order.getOrdId());
        order.setGoNum(this.orderDetailDao.selectGoodsTypeNum(order.getOrdId()));
        order.setOrdTotalPri(this.orderDetailDao.selectOrdTotalPriByOrdId(order.getOrdId()));
        order.setReAddressId(this.receiveAddressDao.getDefaultReAddressIdByAccId(accId));
        order.setShipStatus("0");
        order.setShipTotalPri(this.orderDetailDao.selectShipTotalPriceByOrdId(order.getOrdId()));
        this.orderDao.updateByPrimaryKey(order);
        return order.getOrdId();
    }

    // 商家进货后确认收货
    @Override
    public boolean businessReceiveGoods(Integer inId) {
        GoodsIn goodsIn = new GoodsIn();
        //修改进货状态为 1
        goodsIn.setInStatus("1");
        goodsIn.setInId(inId);
        boolean flag = this.goodsInDao.updateGoodsInByInId(goodsIn);
        return flag;
    }

    @Override
    public Integer selectAllGoodsNum(String goNm, Integer accId) {
        Integer schoolId = this.accountDao.selectSchoolIdByAccId(accId);
        return this.goodsDao.selectAllGoodsNum(goNm, schoolId);
    }

    //根据商品id 查询其图片集合
    @Override
    public List<GoodsImg> selectGoodsImgListByGoId(Integer goId) {
        List<GoodsImg> goodsImgList = this.goodsImgDao.selectGoodsImgListByGoId(goId);
        return goodsImgList;
    }

    //根据商家id查询某商家商品数量
    @Override
    public Integer countGoodsNumByAccId(Integer accId, Integer goStatus, String goNm) {
        Integer count = this.goodsDao.countGoodsNumByAccId(accId,goStatus,goNm);
        return count;
    }

    //统计某商家进货记录数
    @Override
    public Integer countGoodsInNumByAccId(Integer accId, String startDate, String endDate) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        if(endDate != null && endDate != ""){
            try {
                date = df.parse(endDate);
                Calendar c = new GregorianCalendar();
                //将 endDate 日期变为日历，并加 1 天，再转换回来变成日期，获取其第二天的日期
                c.setTime(date);
                c.add(Calendar.DAY_OF_MONTH, 1);
                date = c.getTime();
                endDate = df.format(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        Integer count = this.goodsInDao.countGoodsInNumByAccId(accId, startDate, endDate);
        return count;
    }

    //根据商家id统计商品退货记录数
    @Override
    public Integer countGoodsReturnNumByAccId(Integer accId, String startDate, String endDate) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        if(endDate != null && endDate != ""){
            try {
                date = df.parse(endDate);
                Calendar c = new GregorianCalendar();
                //将 endDate 日期变为日历，并加 1 天，再转换回来变成日期，获取其第二天的日期
                c.setTime(date);
                c.add(Calendar.DAY_OF_MONTH, 1);
                date = c.getTime();
                endDate = df.format(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        Integer count = this.goodsReturnDao.countGoodsReturnNumByAccId(accId, startDate, endDate);
        return count;
    }


    //根据商品id查询商家所有进货记录（也可根据某段日期查询）
    @Override
    public List<GoodsIn> selectGoodsInListByAccId(Integer accId, String startDate, String endDate, Integer pageCurrent, Integer pageSize) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        if(endDate != null && endDate != ""){
            try {
                date = df.parse(endDate);
                Calendar c = new GregorianCalendar();
                //将 endDate 日期变为日历，并加 1 天，再转换回来变成日期，获取其第二天的日期
                c.setTime(date);
                c.add(Calendar.DAY_OF_MONTH, 1);
                date = c.getTime();
                endDate = df.format(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        List<GoodsIn> goodsInList = this.goodsInDao.selectGoodsInListByAccId(accId, startDate, endDate, (pageCurrent-1)*pageSize, pageSize);
        return goodsInList;
    }

    //根据商品id查询商家所有退货记录（也可根据某段日期查询）
    @Override
    public List<GoodsReturn> selectGoodsReturnListByAccId(Integer accId, String startDate, String endDate, Integer pageCurrent, Integer pageSize) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        if(endDate != null && endDate != ""){
            try {
                date = df.parse(endDate);
                Calendar c = new GregorianCalendar();
                //将 endDate 日期变为日历，并加 1 天，再转换回来变成日期，获取其第二天的日期
                c.setTime(date);
                c.add(Calendar.DAY_OF_MONTH, 1);
                date = c.getTime();
                endDate = df.format(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        List<GoodsReturn> goodsReturnList = this.goodsReturnDao.selectGoodsReturnListByAccId(accId, startDate, endDate, (pageCurrent-1)*pageSize, pageSize);
        return goodsReturnList;
    }
}
